package com.ywb.edugui.dao.impl;

import com.ywb.edugui.utils.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import static com.ywb.edugui.utils.JDBCUtils.getConnection;

/**
 * BaseDaoImpl提取所有DaoImpl通用的代码,接受sql返回对应结果
 * @param <T>
 */
public class BaseDaoImpl<T> {
    Connection conn = null;
    QueryRunner qr = new QueryRunner();

    /**
     * List和getOne方法不需要子类传入实体类的类型依然可以返回相应的实体类的核心：
     * 1. 获取该类继承的泛型对象组
     * 2. 获取数组里的第一个泛型T的实际类型
     */
    ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
    Class clazz = (Class) pt.getActualTypeArguments()[0];
    /**
     * 增删改通用
     * @param sql  传入想要执行的sql预编译语句 insert delete update都可以
     * @param parameters 传入sql语句中?的具体值
     * @return 受到影响的行数
     */
    public int update(String sql, Object... parameters) {
        int result = 0;
        try{
            conn = getConnection();
            //将更新结果返回
            result = qr.update(conn, sql, parameters);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
//            一定要关闭连接，否则连接池达到上线之后会永久堵塞,
            JDBCUtils.close(conn, null, null);
        }
        return result;
    }

    /**
     * 返回clazz类型的list集合
     * @param sql
     * @param parameters
     * @return list<clazz>
     */
    public List<T> list(String sql, Object... parameters) {
        List<T> list = null;
        try{
            conn = getConnection();
//            QuerryRunner在调用query方法的时候会将结果集传入BeanListHandler,
//            其会将ResultSet转化为我们传入的class类型的List返回
            list = qr.query(conn, sql, new BeanListHandler<T>(clazz), parameters);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtils.close(conn, null, null);
        }
        return list;
    }


    /**
     * 返回一个结果
     * @param sql
     * @param parameters
     * @return
     */
    public T getOne(String sql, Object... parameters) {
        T t = null;
        try{
            conn = getConnection();

            t =  qr.query(conn, sql, new BeanHandler<T>(clazz), parameters);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }  finally {
            JDBCUtils.close(conn, null, null);
        }
        return t;
    }

    /**
     * 返回一个结果的具体某个值,一行一列的数据
     * @param sql
     * @param parameters
     * @return
     */
    public Object getOneColumn(String sql, Object... parameters) {
        Object o = null;
        try{
            conn = getConnection();
//
            o = qr.query(sql, new ScalarHandler<>(), parameters);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtils.close(conn, null, null);
        }
        return o;
    }

    /**
     * 批处理操作
     * 用于科目文件上传主
     * @param sql
     * @param parameters
     * @return
     */
    public int[] batch(String sql, Object[][] parameters){
        int[] result = null;
        try{
            conn = getConnection();

            result = qr.batch(conn, sql, parameters);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

}
